
package com.hlkj.pay.app.merchant.impl;

import java.util.List;
import java.util.Set;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.pay.app.merchant.IMerchantInfoApplicationAppService;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantReportExtPt;
import com.hlkj.pay.app.payment.IMerchantPaymentAppService;
import com.hlkj.pay.dto.merchant.ReportChannelParamsDto;
import com.hlkj.pay.dto.merchant.config.MerchantPaymentConfigMappingDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportResDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.gateway.merchant.IMerchantReportGateway;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantReportAmountDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantReportInfoDO;
import com.hlkj.pay.service.common.IOperatedLogService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.merchant.IMerchantReportAmountService;
import com.hlkj.pay.service.merchant.IMerchantReportService;

import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/09/25 13:09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantReportChannelService {

    private final IMerchantReportService merchantReportService;

    private final IOperatedLogService merchantAccessLogService;

    private final IMerchantInfoApplicationAppService merchantInfoApplicationAppService;

    private final IMerchantApplicationService merchantApplicationService;

    private final ExtensionExecutor extensionExecutor;

    private final IMerchantReportGateway merchantReportGateway;

    private final IMerchantReportAmountService merchantReportAmountService;

    private final IMerchantPaymentAppService merchantPaymentAppService;

    private final IMerchantConfigService merchantConfigService;

    public boolean extensionExist(String channelCode) {
        return merchantReportGateway.extensionExist(channelCode);
    }

    /**
     * 进件
     *
     * @param merchantAccessDto
     */
    public boolean processReportApply(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        if (merchantReportInfo == null) {
            log.warn("processAccessMessage 数据不存在 id:{}", merchantReportInfo.getId());
            return false;
        }
        Long id = merchantReportInfo.getId();
        CommonResult<MerchantReportResDto> accessResDtoCommonResult = merchantReportGateway.submitChannelReport(merchantAccessDto);
        MerchantReportInfoDO updateMerchantReportInfoDO = new MerchantReportInfoDO();
        updateMerchantReportInfoDO.setId(id);
        if (accessResDtoCommonResult.isSuccess()) {
            MerchantReportResDto merchantAccessResDto = accessResDtoCommonResult.getData();
            Integer accessStatus = merchantAccessResDto.getReportStatus().getCode();
            if (merchantReportInfo.getLastStatus() > accessStatus) {
                // 更新完信息后回到上一个状态
                accessStatus = merchantReportInfo.getLastStatus();
            }
            if (StringUtils.hasText(merchantAccessResDto.getExtendA())) {
                updateMerchantReportInfoDO.setExtendA(merchantAccessResDto.getExtendA());
            }
            if (StringUtils.hasText(merchantAccessResDto.getVirtualAccountNo())) {
                updateMerchantReportInfoDO.setVirtualAccountNo(merchantAccessResDto.getVirtualAccountNo());
            }
            if (StringUtils.hasText(merchantAccessResDto.getBankCardId())) {
                updateMerchantReportInfoDO.setBankCardId(merchantAccessResDto.getBankCardId());
            }
            updateMerchantReportInfoDO.setStatus(accessStatus);
            updateMerchantReportInfoDO.setMessage("");
            updateMerchantReportInfoDO.setSubMchId(merchantAccessResDto.getSubMchId());
            merchantAccessLogService.save(updateMerchantReportInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "机构报备成功", "渠道报备成功");
        }
        else {
            updateMerchantReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
            updateMerchantReportInfoDO.setMessage(accessResDtoCommonResult.getMsg());
            merchantAccessLogService.save(updateMerchantReportInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "机构报备驳回", accessResDtoCommonResult.getMsg());
        }
        updateMerchantReportInfoDO.setLastStatus(merchantReportInfo.getStatus());
        merchantReportService.updateReportInfo(updateMerchantReportInfoDO);
        return accessResDtoCommonResult.isSuccess();
    }

    /**
     * 进件查询
     *
     * @param merchantAccessDto
     */
    public boolean applyQuery(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfoDO = merchantAccessDto.getMerchantReportInfo();
        CommonResult<MerchantReportResDto> accessResDtoCommonResult = merchantReportGateway.merchantReportQuery(merchantReportInfoDO);
        MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
        updateReportInfoDO.setId(merchantReportInfoDO.getId());
        if (accessResDtoCommonResult.isSuccess()) {
            MerchantReportResDto merchantAccessResDto = accessResDtoCommonResult.getData();
            if (merchantAccessResDto.getReportStatus() != null) {
                updateReportInfoDO.setStatus(merchantAccessResDto.getReportStatus().getCode());
                updateReportInfoDO.setLastStatus(merchantReportInfoDO.getStatus());
            }
            if (merchantAccessResDto.getReportBankStatus() != null) {
                updateReportInfoDO.setBankStatus(merchantAccessResDto.getReportBankStatus().getCode());
            }
            if (StringUtils.hasText(merchantAccessResDto.getExtendA())) {
                updateReportInfoDO.setExtendA(merchantAccessResDto.getExtendA());
            }
            if (StringUtils.hasText(merchantAccessResDto.getVirtualAccountNo())) {
                updateReportInfoDO.setVirtualAccountNo(merchantAccessResDto.getVirtualAccountNo());
            }
            if (StringUtils.hasText(merchantAccessResDto.getBankCardId())) {
                updateReportInfoDO.setBankCardId(merchantAccessResDto.getBankCardId());
            }
            if (StringUtils.hasText(merchantAccessResDto.getSignLink())) {
                updateReportInfoDO.setSignLink(merchantAccessResDto.getSignLink());
            }
            // switch (merchantAccessResDto.getReportStatus()) {
            //     // 审批通过 需要将数据加入到子商户信息
            //     case APPROVE_SUCCESS:
            //         // 获取通道参数
            //         ReportChannelParamsDto accessChannelParamsDto = new ReportChannelParamsDto();
            //         accessChannelParamsDto.setUserId(merchantReportInfoDO.getUserId());
            //         accessChannelParamsDto.setBankCardId(merchantReportInfoDO.getBankCardId());
            //         accessChannelParamsDto.setExtendA(merchantReportInfoDO.getExtendA());
            //         accessChannelParamsDto.setVirtualAccountNo(merchantReportInfoDO.getVirtualAccountNo());
            //         String channelParams = extensionExecutor.execute(ChannelMerchantReportExtPt.class, BizScenario.valueOf(merchantReportInfoDO.getChannelCode()),
            //                 ex -> ex.channelParams(accessChannelParamsDto));
            //         MerchantAccessInfoDO merchantAccessInfo = BeanUtil.copyProperties(merchantReportInfoDO, MerchantAccessInfoDO.class);
            //         merchantInfoApplicationAppService.addAppChannelInfo(merchantAccessInfo, channelParams, MerchantEnum.DATA_RELATION_TYPE.REPORT);
            //         break;
            //     default:
            // }
        }
        else {
            updateReportInfoDO.setMessage(accessResDtoCommonResult.getMsg());
            updateReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
        }
        merchantReportService.updateReportInfo(updateReportInfoDO);
        return accessResDtoCommonResult.isSuccess();
    }
    /**
     *
     * @param merchantAccessDto
     * @return
     */
    public boolean processSign(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfoDO = merchantAccessDto.getMerchantReportInfo();
        CommonResult<MerchantReportResDto> accessResDtoCommonResult = merchantReportGateway.merchantReportSign(merchantReportInfoDO);
        MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
        updateReportInfoDO.setId(merchantReportInfoDO.getId());
        if (accessResDtoCommonResult.isSuccess()) {
            MerchantReportResDto merchantAccessResDto = accessResDtoCommonResult.getData();
            if (merchantAccessResDto.getReportStatus() != null) {
                updateReportInfoDO.setStatus(merchantAccessResDto.getReportStatus().getCode());
                updateReportInfoDO.setLastStatus(merchantReportInfoDO.getStatus());
            }
            if (merchantAccessResDto.getReportBankStatus() != null) {
                updateReportInfoDO.setBankStatus(merchantAccessResDto.getReportBankStatus().getCode());
            }
            if (StringUtils.hasText(merchantAccessResDto.getExtendA())) {
                updateReportInfoDO.setExtendA(merchantAccessResDto.getExtendA());
            }
            if (StringUtils.hasText(merchantAccessResDto.getVirtualAccountNo())) {
                updateReportInfoDO.setVirtualAccountNo(merchantAccessResDto.getVirtualAccountNo());
            }
            if (StringUtils.hasText(merchantAccessResDto.getBankCardId())) {
                updateReportInfoDO.setBankCardId(merchantAccessResDto.getBankCardId());
            }
            if (StringUtils.hasText(merchantAccessResDto.getSignLink())) {
                updateReportInfoDO.setSignLink(merchantAccessResDto.getSignLink());
            }
        }
        else {
            updateReportInfoDO.setMessage(accessResDtoCommonResult.getMsg());
            updateReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
        }
        merchantReportService.updateReportInfo(updateReportInfoDO);
        return accessResDtoCommonResult.isSuccess();
    }
    /**
     *
     * @param merchantAccessDto
     * @return
     */
    public boolean processSignQuery(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfoDO = merchantAccessDto.getMerchantReportInfo();
        CommonResult<MerchantReportResDto> accessResDtoCommonResult = merchantReportGateway.merchantReportSignQuery(merchantReportInfoDO);
        MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
        updateReportInfoDO.setId(merchantReportInfoDO.getId());
        if (accessResDtoCommonResult.isSuccess()) {
            MerchantReportResDto merchantAccessResDto = accessResDtoCommonResult.getData();
            if (merchantAccessResDto.getReportStatus() != null) {
                updateReportInfoDO.setStatus(merchantAccessResDto.getReportStatus().getCode());
                updateReportInfoDO.setLastStatus(merchantReportInfoDO.getStatus());
            }
            if (merchantAccessResDto.getReportBankStatus() != null) {
                updateReportInfoDO.setBankStatus(merchantAccessResDto.getReportBankStatus().getCode());
            }
            if (StringUtils.hasText(merchantAccessResDto.getExtendA())) {
                updateReportInfoDO.setExtendA(merchantAccessResDto.getExtendA());
            }
            if (StringUtils.hasText(merchantAccessResDto.getVirtualAccountNo())) {
                updateReportInfoDO.setVirtualAccountNo(merchantAccessResDto.getVirtualAccountNo());
            }
            if (StringUtils.hasText(merchantAccessResDto.getBankCardId())) {
                updateReportInfoDO.setBankCardId(merchantAccessResDto.getBankCardId());
            }
            if (StringUtils.hasText(merchantAccessResDto.getSignLink())) {
                updateReportInfoDO.setSignLink(merchantAccessResDto.getSignLink());
            }
            // switch (merchantAccessResDto.getReportStatus()) {
            //     // 审批通过 需要将数据加入到子商户信息
            //     case APPROVE_SUCCESS:
            //         // 获取通道参数
            //         ReportChannelParamsDto accessChannelParamsDto = new ReportChannelParamsDto();
            //         accessChannelParamsDto.setUserId(merchantReportInfoDO.getUserId());
            //         accessChannelParamsDto.setBankCardId(merchantReportInfoDO.getBankCardId());
            //         accessChannelParamsDto.setExtendA(merchantReportInfoDO.getExtendA());
            //         accessChannelParamsDto.setVirtualAccountNo(merchantReportInfoDO.getVirtualAccountNo());
            //         String channelParams = extensionExecutor.execute(ChannelMerchantReportExtPt.class, BizScenario.valueOf(merchantReportInfoDO.getChannelCode()),
            //                 ex -> ex.channelParams(accessChannelParamsDto));
            //         MerchantAccessInfoDO merchantAccessInfo = BeanUtil.copyProperties(merchantReportInfoDO, MerchantAccessInfoDO.class);
            //         merchantInfoApplicationAppService.addAppChannelInfo(merchantAccessInfo, channelParams, MerchantEnum.DATA_RELATION_TYPE.REPORT);
            //         break;
            //     default:
            // }
        }
        else {
            updateReportInfoDO.setMessage(accessResDtoCommonResult.getMsg());
            updateReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
        }
        merchantReportService.updateReportInfo(updateReportInfoDO);
        return accessResDtoCommonResult.isSuccess();
    }
    /**
     *
     * @param merchantAccessDto
     * @return
     */
    public boolean allot(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        MerchantReportAmountDO merchantReportAmountDO = merchantReportAmountService.queryAmountByReportId(merchantReportInfo.getId(),
                MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.INIT);
        if (merchantReportAmountDO == null) {
            log.info("发起调拨 当前报备没有需要执行的代付金额信息 reportId:{}", merchantReportInfo.getId());
            return false;
        }
        CommonResult<MerchantReportResDto> accessResDtoCommonResult = merchantReportGateway.merchantReportAllot(merchantReportInfo, merchantReportAmountDO);
        MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
        updateReportInfoDO.setId(merchantReportInfo.getId());
        if (accessResDtoCommonResult.isSuccess()) {
            MerchantReportAmountDO updateMerchantReportAmountDO = new MerchantReportAmountDO();
            updateMerchantReportAmountDO.setId(merchantReportAmountDO.getId());
            updateMerchantReportAmountDO.setProcessStatus(MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.ALLOT.getCode());
            merchantReportAmountService.updateReportAmount(updateMerchantReportAmountDO);
            updateReportInfoDO.setAuditStatus(MerchantEnum.REPORT_CHANNEL_CONFIG_STATUS.BANK_ALLOT_QUERY.getCode());
            merchantAccessLogService.save(merchantReportInfo.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "调拨成功", "发起调拨成功，调拨金额" + merchantReportAmountDO.getAmount());
        }
        else {
            updateReportInfoDO.setMessage(accessResDtoCommonResult.getMsg());
            merchantAccessLogService.save(merchantReportInfo.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "调拨失败", "发起调拨失败" + accessResDtoCommonResult.getMsg());
        }
        merchantReportService.updateReportInfo(updateReportInfoDO);
        return accessResDtoCommonResult.isSuccess();
    }

    /**
     *
     * @param merchantAccessDto
     * @return
     */
    public boolean allotQuery(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        MerchantReportAmountDO merchantReportAmountDO = merchantReportAmountService.queryAmountByReportId(merchantReportInfo.getId(),
                MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.ALLOT);
        if (merchantReportAmountDO == null) {
            log.info("调拨查询 当前报备没有需要执行的代付金额信息 reportId:{}", merchantReportInfo.getId());
            return false;
        }
        MerchantReportAmountDO updateMerchantReportAmountDO = merchantReportGateway.merchantReportAllotQuery(merchantReportInfo, merchantReportAmountDO);
        if (!updateMerchantReportAmountDO.getProcessStatus().equals(merchantReportAmountDO.getProcessStatus())) {
            updateMerchantReportAmountDO.setId(merchantReportAmountDO.getId());
            updateMerchantReportAmountDO.setProcessStatus(MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.PAYMENT.getCode());
            merchantReportAmountService.updateReportAmount(updateMerchantReportAmountDO);
            if (MerchantEnum.PROCESS_STATUS.SUCCESS.getCode().equals(updateMerchantReportAmountDO.getProcessStatus())) {
                MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
                updateReportInfoDO.setId(merchantReportInfo.getId());
                updateReportInfoDO.setAuditStatus(MerchantEnum.REPORT_CHANNEL_CONFIG_STATUS.PAYMENT.getCode());
                merchantReportService.updateReportInfo(updateReportInfoDO);
            }
        }
        return true;
    }

    /**
     *
     * @param merchantAccessDto
     * @return
     */
    public boolean payment(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryDetailByAccessId(merchantReportInfo.getId(), MerchantEnum.DATA_RELATION_TYPE.REPORT);
        List<MerchantPaymentConfigMappingDto> merchantReportPaymentConfigList = merchantConfigService.queryConfigMappingList(merchantReportInfo.getId().toString(),
                MerchantEnum.DATA_RELATION_TYPE.REPORT.getCode());
        MerchantReportInfoDO updateReportInfoDO = new MerchantReportInfoDO();
        updateReportInfoDO.setId(merchantReportInfo.getId());
        MerchantReportAmountDO merchantReportAmountDO = merchantReportAmountService.queryAmountByReportId(merchantReportInfo.getId(),
                MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.PAYMENT);
        if (merchantReportAmountDO == null) {
            log.info("发起代付 当前报备没有需要执行的代付金额信息 reportId:{}", merchantReportInfo.getId());
            return false;
        }
        CommonResult<Set<String>> commonResult = merchantPaymentAppService.addReportPayment(merchantAppChannelDO, merchantReportAmountDO.getAmount(),
                merchantReportPaymentConfigList);
        MerchantReportAmountDO merchantReportAmount = new MerchantReportAmountDO();
        merchantReportAmount.setId(merchantReportAmountDO.getId());
        if (commonResult.isSuccess()) {
            merchantReportAmount.setProcessStatus(MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.DOING.getCode());
            merchantReportAmount.setPaymentId(JsonUtils.toJsonString(commonResult.getData()));
            merchantAccessLogService.save(merchantReportInfo.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "代付成功", "发起代付请求成功，代付金额" + merchantReportAmountDO.getAmount());
        }
        else {
            merchantReportAmount.setProcessStatus(MerchantEnum.REPORT_AMOUNT_PROCESS_STATUS.FAIL.getCode());
            merchantAccessLogService.save(merchantReportInfo.getId(), MerchantEnum.MERCHANT_LOG_TYPE.REPORT, "代付失败", "发起代付请求失败，" + commonResult.getMsg());
        }
        merchantReportAmountService.updateReportAmount(merchantReportAmount);
        return true;
    }

    public void syncChannel(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        // 获取通道参数
        ReportChannelParamsDto accessChannelParamsDto = new ReportChannelParamsDto();
        accessChannelParamsDto.setUserId(merchantReportInfo.getUserId());
        accessChannelParamsDto.setBankCardId(merchantReportInfo.getBankCardId());
        accessChannelParamsDto.setExtendA(merchantReportInfo.getExtendA());
        accessChannelParamsDto.setVirtualAccountNo(merchantReportInfo.getVirtualAccountNo());
        String channelParams = extensionExecutor.execute(ChannelMerchantReportExtPt.class, BizScenario.valueOf(merchantReportInfo.getChannelCode()),
                ex -> ex.channelParams(accessChannelParamsDto));
        MerchantAccessInfoDO merchantAccessInfoDO = BeanUtil.copyProperties(merchantReportInfo, MerchantAccessInfoDO.class);
        merchantInfoApplicationAppService.addAppChannelInfo(merchantAccessInfoDO, channelParams, null,MerchantEnum.DATA_RELATION_TYPE.REPORT);
    }

    /**
     * 系统认证
     *
     * @param merchantAccessDto
     */
    public boolean systemAuth(MerchantReportDto merchantAccessDto) {
        MerchantReportInfoDO updateMerchantReportInfoDO = new MerchantReportInfoDO();
        updateMerchantReportInfoDO.setId(merchantAccessDto.getMerchantReportInfo().getId());
        updateMerchantReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.CHANNEL_WAIT_APPROVE.getCode());
        merchantReportService.updateReportInfo(updateMerchantReportInfoDO);
        return true;
    }



}
